#include "tuplesense.h"
#include <map>
#include <set>
#include <unordered_map>

void TupleSense::getAllpossibleTuples(string sensetable_name) {
	int sense_index = -1;
	for (int i = 0; i < all_tables.size(); i++) {
		if (all_tables[i].table_name == sensetable_name) {
			sense_index = i;
			break;
		}
	}
	if (sense_index == -1) {
		cout << "[Error   ] no this sense table : " << sensetable_name << endl;
		exit(0);
	}
	
	//cout << "sense_index " << sense_index << endl;

	map<string, set<string>> col_values;
	set<string> sense_cols;
	for (int i = 0; i < all_tables[sense_index].column_names.size(); i++) {
		sense_cols.insert(all_tables[sense_index].column_names[i]);
	}

	for (int i = 0; i < all_tables.size(); i++) {
		if (i != sense_index) {
			//cout << "i :" << i << endl;
			for (int j = 0; j < all_tables[i].column_names.size(); j++) {
				string colname = all_tables[i].column_names[j];
				if (sense_cols.count(colname)) {
					//cout << "colname " << colname << endl;
					if (col_values.count(colname) == 0) {
						col_values[colname] = set<string>();
					}
					int row = all_tables[i].values[0].size();
					for (int k = 0; k < row; k++) {
						//cout << "value : " << all_tables[i].values[j][k] << endl;
						col_values[colname].insert(all_tables[i].values[j][k]);
					}
				}
			}
		}
	}

	for (auto& p : col_values) {
		cout << "colname : " << p.first << endl;
		for (auto& s : p.second) {
			cout << s << endl;
		}
	}

}

void TupleSense::computeTupleSense(string sql_temp) {
	int row_num = all_tables[0].values[0].size();
	vector<string> res;

	//row_num = min(3000, row_num);
	for (int i = 0; i < row_num; i++) {
		if (i % 1000 == 0) cout << i  << " / " << row_num << endl;
		string sql = sql_temp + "'" + to_string(i) + "'";
		PGresult* pgres = PQexec(conn, sql.c_str());
		int row = PQntuples(pgres);
		int col = PQnfields(pgres);
		for (int k = 0; k < row; k++) {
			string value;
			for (int j = 0; j < col; j++) {
				value += string(PQgetvalue(pgres, k, j)) + "|";
			}
			res.push_back(value);
		}
	}
	
	int res_size = res.size();

	int show_row = min(30, res_size);

	cout << "res rows : " << res_size << endl;
	for (int i = 0; i < show_row; i++) {
		cout << res[i] << endl;
	}


}

void TupleSense::computeTupleSenseGroup(string sql_temp,string group) {
	int row_num = all_tables[0].values[0].size();
	vector<string> res;

	//row_num = min(3000, row_num);
	for (int i = 0; i < row_num; i++) {
		if (i % 1000 == 0) cout << i << " / " << row_num << endl;
		string sql = sql_temp + "'" + to_string(i) + "'";
		sql += "group by " + group;
		PGresult* pgres = PQexec(conn, sql.c_str());
		int row = PQntuples(pgres);
		int col = PQnfields(pgres);
		for (int k = 0; k < row; k++) {
			string value;
			for (int j = 0; j < col; j++) {
				value += string(PQgetvalue(pgres, k, j)) + "|";
			}
			res.push_back(value);
		}
	}

	int res_size = res.size();

	int show_row = min(30, res_size);

	cout << "res rows : " << res_size << endl;
	for (int i = 0; i < show_row; i++) {
		cout << res[i] << endl;
	}


}